package wxdb.index.btree;

import java.io.Serializable;

import wxdb.index.btree.DirEntry;
import wxdb.query.Constant;
import wxdb.record.RID;
import wxdb.record.TableInfo;

public class BTreeLeaf implements Serializable{
	
	
	private TableInfo ti;
	private BTreePage content;
	private int currentslot;
	private Constant searchKey;
	
	public BTreeLeaf(int pid, Constant searchKey, TableInfo ti){
		this.ti = ti;
		this.searchKey = searchKey;
		this.content = new BTreePage(pid, ti);
		if(searchKey == null)
			currentslot = -1;
		else
			this.currentslot = content.findFirstSlotBefore(searchKey);
	}
	
	public boolean next(){
		if(searchKey == null)
			return false;
		++currentslot;
		if(currentslot >= content.getTotalSlotNum())
			return tryOverFlowPage();
		else if(content.getFldVal(currentslot, "dataval").equals(searchKey))
				return true;
		else
			return tryOverFlowPage();
	}
	
	public boolean nextSlot(){
		++currentslot;
		if(currentslot >= content.getTotalSlotNum())
			return tryOverFlowPage();
		else
			return true;
	}
	
	public boolean preSlot(){
		--currentslot;
		if(currentslot >= 0){	
			return true;
		}
		return false;
	}
	
	public RID getDataRid(){
		return content.getDataRid(currentslot);
	}
	
	public int getLeafPid(){
		return content.getCurrnetPid();
	}
	
	public void delete(RID rid){
		do{
			if(currentslot < 0)
				currentslot = 0;
			if(getDataRid().equals(rid)){
				content.delete(currentslot);
				return;
			}
		}while(next());
	}
	
	public DirEntry insert(RID rid) {
		++currentslot;
		content.insertLeaf(currentslot, searchKey, rid);
		if(!content.isFull())
			return null;
		//the split this page
		Constant firstKey = content.getFldVal(0, "dataval");
		Constant lastKey = content.getFldVal(content.getTotalSlotNum()-1, "dataval");
		if(firstKey.equals(lastKey)){
			//create overflow page to store all but first record
			int pid = content.split(1, content.getFlag());
			int flag = pid;				//flag is the pid of the overflow page
			content.setFlag(flag);	
			return null;
		}
		else{
			int splitpos = content.getTotalSlotNum()/2;
			Constant splitVal = content.getFldVal(splitpos, "dataval");
			if(splitVal.equals(firstKey)){
				//move right until getting the first non-firstKey-value postion
				while(content.getFldVal(splitpos, "dataval").equals(firstKey))
					++splitpos;
				splitVal = content.getFldVal(splitpos, "dataval");
			}else{
				//move left until getting the first firstKey-value position
				while(content.getFldVal(splitpos, "dataval").equals(firstKey))
					--splitpos;
				splitVal = content.getFldVal(splitpos, "dataval");
			}
			int pid = content.split(splitpos, -1);
			return new DirEntry(splitVal, pid);
		}
		
	}
	
	public boolean tryOverFlowPage(){
		Constant firstKey = content.getFldVal(0, "dataval");
		int flag = content.getFlag();
		if(!firstKey.equals(searchKey) || flag<0)
			return false;
		//else it has overflow page
		int pid = flag;		//overflow page's pid
		content = new BTreePage(pid, ti);
		currentslot = 0;
		return true;
	}
}
